package com.iplant.base.utils.sql.orm;

import com.iplant.base.po.enums.DBEnumType;
import com.iplant.base.utils.general.StringUtils;
import org.slf4j.LoggerFactory;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author xiuto
 */
public class DMLTool {

    private static org.slf4j.Logger logger = LoggerFactory.getLogger(DMLTool.class);

    private static DMLTool _Instance = new DMLTool();

    public static DMLTool GetInstance() {
        return _Instance;
    }


    @SuppressWarnings("AlibabaAvoidPatternCompileInMethod")
    public String MySqlChangeToSqlServer(String wMySqlString) {
        String wResult = "";
        try {
            StringBuffer wStringBuffer = new StringBuffer("");

            Matcher wMatcher = Pattern.compile(
                    "SELECT\\s+LAST_INSERT_ID\\(\\)(\\s+as\\s+ID)?\\s*\\;", Pattern.CASE_INSENSITIVE).matcher(
                    wMySqlString);
            if (wMatcher.matches()) {
                wMySqlString = wMatcher.replaceAll("");

                wMatcher = Pattern.compile("\\)\\s*VALUES\\s*\\(", Pattern.CASE_INSENSITIVE).matcher(wMySqlString);
                if (wMatcher.matches()) {
                    wMySqlString = wMatcher.replaceAll(") output inserted.* \\n VALUES (");
                }
            }
            wMySqlString = wMySqlString.replaceAll("now()", "GETDATE()");

            wMySqlString.replaceAll("\\s+limit\\s+(?<Num>\\d+)\\s*\\,?(?<Num2>\\d*)",
                    " offset $1  rows fetch next $2 row only");

            wMatcher = Pattern.compile("\\`(?<Column>[a-zA-Z]+[a-zA-Z0-9_]+)\\`", Pattern.CASE_INSENSITIVE).matcher(
                    wMySqlString);
            wStringBuffer.setLength(0);

            while (wMatcher.find()) {
                wMatcher.appendReplacement(wStringBuffer, wMatcher.group("Column"));
            }

            wMatcher.appendTail(wStringBuffer);
            wMySqlString = wStringBuffer.toString();

            wMatcher = Pattern.compile(
                    "str_to_date\\(\\s*(?<STR>[\\']{1,2}2010\\-01\\-01[\\']{1,2})\\s*\\,\\s*[\\']{1,2}\\%Y\\-\\%m\\-\\%d\\s*\\%H[\\']{1,2}\\)",
                    Pattern.CASE_INSENSITIVE).matcher(wMySqlString);
            wStringBuffer.setLength(0);

            while (wMatcher.find()) {
                wMatcher.appendReplacement(wStringBuffer,
                        String.format("cast( %s  as datetime)", wMatcher.group("STR")));
            }

            wMatcher.appendTail(wStringBuffer);
            wMySqlString = wStringBuffer.toString();

            wResult = wMySqlString;

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
        }

        return wResult;
    }

    public String DMLChange(String wMySqlString, DBEnumType wSQLTypeField) {
        switch (wSQLTypeField) {
            case MySQL:
                wMySqlString = wMySqlString.replaceAll("\\\\", "\\\\\\\\");
                break;
            case SQLServer:
                wMySqlString = this.MySqlChangeToSqlServer(wMySqlString);
                break;
            case Oracle:

                break;
            case Access:

                break;
            default:
                break;
        }
        return wMySqlString;
    }


    public String GetMySqlType(String wTypeName, int wLength) {

        String wResult = wTypeName;
        switch (wTypeName.toLowerCase()) {
            case "int":
            case "integer":
                wResult = "int(11)";
                break;
            case "long":
                wResult = "bigint(20)";
                break;
            case "char":
            case "character":
                wResult = "varchar(1)";
                break;
            case "boolean":
                wResult = "TINYINT(4)";
                break;
            case "double":
                wResult = "double";
                break;
            case "float":
                wResult = "float";
                break;
            case "short":
                wResult = "SMALLINT";
                break;
            case "byte":
                wResult = "TINYINT";
                break;
            case "calendar":
            case "date":
                wResult = "datetime";
                break;
            default:
                wResult = StringUtils.Format("varchar({0})", wLength);
                break;
        }
        return wResult;
    }

    public String GetSqlServerType(String wTypeName, int wLength) {

        String wResult = wTypeName;
        switch (wTypeName.toLowerCase()) {

            case "int":
            case "integer":
                wResult = "[int]";
                break;
            case "long":
                wResult = "[bigint]";
                break;
            case "char":
            case "character":
                wResult = "[varchar(1)]";
                break;
            case "boolean":
            case "byte":
                wResult = "[tinyint]";
                break;
            case "double":
                wResult = "[float]";
                break;
            case "float":
                wResult = "[real]";
                break;
            case "short":
                wResult = "[smallint]";
                break;
            case "calendar":
            case "date":
                wResult = "[datetimeoffset]";
                break;
            default:
                wResult = StringUtils.Format("[nvarchar]({0})", wLength);
                break;
        }
        return wResult;
    }

}
